package com.sktlab.bizconfmobile.mina;


import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import com.sktlab.bizconfmobile.model.ConfControl;
import com.sktlab.bizconfmobile.model.Conference;
import com.sktlab.bizconfmobile.model.ConferenceAccount;
import com.sktlab.bizconfmobile.model.ConferenceAttr;
import com.sktlab.bizconfmobile.model.Participant;
import com.sktlab.bizconfmobile.model.manager.CommunicationManager;
import com.sktlab.bizconfmobile.model.manager.ConferenceManager;
import com.sktlab.bizconfmobile.model.manager.ContactManager;
import com.sktlab.bizconfmobile.net.Response;
import com.sktlab.bizconfmobile.net.ServerLinkSession;
import com.sktlab.bizconfmobile.net.StatusCode;
import com.sktlab.bizconfmobile.util.CharSetUtil;
import com.sktlab.bizconfmobile.util.Util;

public class ClientMinaHandler extends IoHandlerAdapter {
	
	public static final String TAG = "ClientMinaHandler";
	
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		
		super.sessionCreated(session);
		System.out.println("sessionCreated~");
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		super.sessionOpened(session);

		System.out.println("sessionOpened~");
		
		ConfControl.getInstance().setServerSession(session);
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		super.sessionClosed(session);
		
		System.out.println("session closed~");
		
		ConfControl.getInstance().disconnectToServer();
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		super.sessionIdle(session, status);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {		
		super.exceptionCaught(session, cause);
		
		Util.BIZ_CONF_DEBUG(TAG, "与" + session.getRemoteAddress() + "通信过程中出现错误:[" + cause.getMessage() + "]..连接即将关闭....");
		
		ConfControl.getInstance().disconnectToServer();
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		
		super.messageReceived(session, message);
		
		String rcv = message.toString();	
		rcv = CharSetUtil.toASCII(rcv);
		
		do{
			
			ConferenceManager cm = ConfControl.getInstance().getConfManager();
						
			String successSignal = MinaUtil.MSG_LS_SL;
			
			String failSignal = StatusCode.CAS_CONNECTED_FAIL_SIGNAL;
						
			if(ServerLinkSession.isUseTestAddress) {
				
				successSignal = StatusCode.CONNECT_SUCCESS;
				failSignal = StatusCode.TEST_CAS_IS_DOWN;
			}
			
			Util.BIZ_CONF_DEBUG(TAG, "receive msg from server: " + rcv);
			
			//when receive fail signal, notify the wait thread
			if (rcv.contains(failSignal)) {
				
				cm.setServerConnected(false);
				
				Util.BIZ_CONF_DEBUG(TAG, "connect to server failed or sever can not work");
				break;
			}
			
			if(rcv.contains(CharSetUtil.toASCII("ERR")) || 
					rcv.contains(CharSetUtil.toASCII("-"))){
				
				Util.BIZ_CONF_DEBUG(TAG, "receive error msg from server");
				break;
			}
			
			if(rcv.contains(CharSetUtil.toASCII(successSignal))) {	
				
				cm.setRevSuccessSignal(true);
				
				cm.createAccSession(session);
				break;
			}
			
			if (!cm.isRevSuccessSignal()) {
				
				break;
			}
			
			if(rcv.contains(CharSetUtil.toASCII(MinaUtil.CREATE_ACC_SESSION))) {
				
				MinaMsg msg = new MinaMsg(rcv);
				
				cm.setAccId(msg.getMsgData().get(1));
				
				cm.createBvSession(session);			
				break;
			}
			
			//if acc not create, not handle other message
			if (!cm.isAccCreated()) {
				
				break;
			}
			
			if(rcv.contains(CharSetUtil.toASCII(MinaUtil.CREATE_BV_SESSION))) {				
				
				MinaMsg msg = new MinaMsg(rcv);					
				
				cm.setBvId(msg.getMsgData().get(1));
				
				Util.BIZ_CONF_DEBUG(TAG, "acc id: " + cm.getAccSession().getId()
										 + " bv id: " + cm.getBvSession().getId());								
				
				cm.requestActiveConfList(session);
				break;
			}
			
			//if BV not create, did not handle other information from server
			if (!cm.isBvCreated()) {
				
				break;
			}
			
			if(rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ACTIVE_CONF_LIST))) {
				
				//cm.getServerLSSession().setConnected(true);
				CommunicationManager.getInstance().clearActiveConfs();
				
				//after this step, we store the active conference list in Communicationmanager's mActiveConfs
				MinaMsg msg = new MinaACLMsg(rcv);				
				
				ConferenceAccount activeAccount = CommunicationManager.getInstance().getActiveAccount();
				
				String confNumber = activeAccount.getConfCode();
				
				Util.BIZ_CONF_DEBUG(TAG, "current active conf num: " + confNumber);
				
				do {
					
					if(!Util.isEmpty(activeAccount.getModeratorPw())) {
						
						//active moderator conference
						cm.activeConf(session);
						break;
					}
					
					if (!CommunicationManager.getInstance().getActiveConfs().containsKey(confNumber)) {
						
						Util.BIZ_CONF_DEBUG(TAG, "current active account code number is not active in bridge,please check");
						break;
					}
					
					Conference cf = CommunicationManager.getInstance().getActiveConfByKey(confNumber);
					
					//when join conference, set the active conference
					ConfControl.getInstance().setActiveConference(cf);
					
					cm.activeConf(session, confNumber);				

				}while(false);
				
				break;
			}
	
			if(rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ACTIVATE_CONF))) {
				
				cm.setConfActived(true);
				
				MinaMsg msg = new MinaMsg(rcv);
				
				ConferenceAttr activeConfAttr = cm.getActiveConference().getAttr();
				
				activeConfAttr.setConfId(msg.getMsgData().get(0));

				cm.assocWithConf(session);			
				break;
			}
			
			if (!cm.isConfActived()) {
				
				break;
			}
			
			if (rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ASSOC_CONF))) {
				
				cm.setConfAssoced(true);
				cm.createAcvSession(session);
				break;
			}
			
			if (!cm.isConfAssoced()) {
				
				break;
			}
			
			if (rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ACV_SA))) {
				
				MinaMsg msg = new MinaMsg(rcv);
				
				String acvSsnId = msg.getSsnId();
				
				cm.setAcvId(acvSsnId);
	
				cm.requestPList(session);
				break;
			}
			
			if (rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ACV_P_LIST))) {
				
				cm.setServerConnected(true);
				
				MinaMsg msg = new MinaPListMsg(rcv);	
				
				ConferenceAccount account = CommunicationManager.getInstance().getActiveAccount();
				
				do{
					
					boolean isGuest = Util.isEmpty(account.getModeratorPw());								
					
					boolean isOutCallEnable = account.isDialOutEnable();
					
					if(!isOutCallEnable){
						
						break;
					}
					
					Participant currentUser = ContactManager.getInstance().getCurrentUserObject();
					
					
					//if the party added had been in conference, do not add again
					if (CommunicationManager.getInstance().getOutCallPartys().contains(currentUser)) {
						
						break;
					}
					
					//add the party to conference
					CommunicationManager.getInstance().addOutCallParty(currentUser);
					
					if(isGuest) {
						
						cm.addPartyToConf(currentUser, false);
						break;
					}
					
					cm.addPartyToConf(currentUser, true);
				}while(false);
				
				break;
			}
			
			if (rcv.contains(CharSetUtil.toASCII(MinaUtil.MSG_ACV_P_A))) {
				
				cm.setServerConnected(true);
				//receive msg format:
				//4C4~0~ACV.P.A~4C6~1~0~wenjuan~018202932163~0~~~~~Shrine~0~0~0~0
				do {
					
					MinaMsg msg = new MinaMsg(rcv);
					
					String acvSsnId = msg.getSsnId();
					
					cm.getAcvSession().setId(acvSsnId);
					
					Util.BIZ_CONF_DEBUG(TAG, " ACV SsnId: " + acvSsnId);
					
					String partyId = msg.getMsgData().get(0);
					
					String msgType = msg.getMsgData().get(1);
					
					//if is not the party attribute related information, not handle
					if ( !msgType.equalsIgnoreCase(MinaUtil.MSG_ACV_PARTY_ATTR)) {
						
						break;
					}
					
					String partyNumber = msg.getMsgData().get(4);
					
					Util.BIZ_CONF_DEBUG(TAG, "parse party number from server:" + partyNumber);
					
					Participant party = ContactManager.getInstance().getSelectedContactByPhoneNum(partyNumber);				
					
					Participant currentUser = ContactManager.getInstance().getCurrentUserObject();
					
					//When we get a null party object from user selected parties, we check whether the party is the 
					//one user specified in dial out moudle
					if (Util.isEmpty(party) && !Util.isEmpty(currentUser.getPhone()) 
							&& partyNumber.contains(currentUser.getPhone())){
						
						party = currentUser;
					}
					
					if (Util.isEmpty(party)) {
						
						Util.BIZ_CONF_DEBUG(TAG, "sorry get party failed,please check ContactManager mSelectedContacts");
						break;
					}
					
					party.setIdInConference(partyId);				
					
					if (party.isOutCalled()){
						
						Util.BIZ_CONF_DEBUG(TAG, "This party had been out called");
						break;
					}
					
					if(party.isModerator()) {
						
						cm.moderatorOutCall(session,party);
					}else {
						
						cm.guestOutCallParty(session,party);
					}
					
					party.setOutCalled(true);
					
				}while(false);		
				
				break;
			}
						
		}while(false);
			
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		
		super.messageSent(session, message);
		
		Util.BIZ_CONF_DEBUG(TAG, "client send msg to server: " + message.toString());
	}
}
